#pragma once
#include <queue>
#include <iostream>
#include <pthread.h>
using std::cout;
using std::endl;

namespace wyl_thread_pool
{
    size_t g_num = 5;
    template <class T>
    class Thread_Pool
    {
    public:
        Thread_Pool(size_t num = g_num) : num_(num)
        {
            pthread_mutex_init(&mutex_, nullptr);
            pthread_cond_init(&isempty_, nullptr);
        }
        ~Thread_Pool()
        {
            pthread_mutex_destroy(&mutex_);
            pthread_cond_destroy(&isempty_);
        }
        // 初始化线程池
        void InitThreadPool()
        {
            pthread_t tid;
            for (int i = 0; i < num_; i++)
            {
                pthread_create(&tid, nullptr, Routine, this);
            }
        }

        static void *Routine(void *args)
        {
            pthread_detach(pthread_self());
            Thread_Pool<T> *t = (Thread_Pool<T> *)args;
            while (true)
            {
                t->Lock();
                // 如果任务队列为空，等待
                while (t->ISEmpty())
                {
                    t->Wait();
                }
                //取出任务运行
                T task;
                t->pop(&task);
                t->Unlock();
                // 运行任务
                task();
            }
        }
        void push(T& in)
        {
            Lock();
            task_queue_.push(in);
            Unlock();
            WakeUp();
        }

    private:
        void WakeUp()
        {
            pthread_cond_signal(&isempty_);
        }
        void pop(T* out)
        {
            *out = task_queue_.front();
            task_queue_.pop();
        }
        void Lock()
        {
            pthread_mutex_lock(&mutex_);
        }
        void Unlock()
        {
            pthread_mutex_unlock(&mutex_);
        }
        bool ISEmpty()
        {
            return task_queue_.empty();
        }
        void Wait()
        {
            pthread_cond_wait(&isempty_, &mutex_);
        }

    private:
        std::queue<T> task_queue_;    // 任务队列
        pthread_mutex_t mutex_;  // 互斥锁
        pthread_cond_t isempty_; // 条件变量
        size_t num_;             // 线程数量
    };

};